// 客户端长连接服务，用于监听远程服务且维持在线
package clientserver

import (
	"context"
	"encoding/json"
	"fmt"
	"io"
	"time"

	"gitee.com/xgotool/sqlite-logs-more/protoc"
	"gitee.com/xiaoyutab/xgotool/xstring"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	"google.golang.org/protobuf/types/known/emptypb"
)

// 开启远程持续性服务
//
//	remote	远程地址
func Start(remote string) {
	fmt.Println("开启远程持续性服务")
	if remote == "" {
		panic("远程地址为空，开启失败")
	}
	if remote[0:7] != "grpc://" {
		panic("持续性服务目前仅支持grpc协议开启，请使用grpc://进行拼接对应地址信息")
	}
	// 连接grpc通信
	conn, err := grpc.Dial(remote[7:],
		grpc.WithTransportCredentials(insecure.NewCredentials()), // 不使用ssl证书进行连接
		grpc.WithPerRPCCredentials(new(ClientTokenAuth)),         // 使用token进行携带token连接
	) // 链接grpc
	if err != nil {
		panic("GRPC连接打开失败：" + err.Error())
	}
	defer conn.Close()
	c := protoc.NewRemoteClient(conn)
	inf, err := c.Info(context.Background(), &emptypb.Empty{})
	if err != nil {
		panic("INFO获取失败：" + err.Error())
	}
	fmt.Println("本客户端详情：", inf)
	// 双向流调用
	query, err := c.QuerySqlListen(context.Background())
	if err != nil {
		panic(err)
	}
	// 接收消息
	go func() {
		for {
			// 接收消息
			msg, err := query.Recv()
			if err != nil {
				if err == io.EOF {
					// 如果错误为读取完成的错误，就跳过本次查询
					continue
				}
				panic(err)
			}
			switch msg.Types {
			case 0:
				// 接收心跳维持
			case 1:
				// 上传/下载【此处为服务器端发送到客户端的，所以具体类型为下载类型，即将服务端发送过来的数据存储到本地上即可】
			}
			time.Sleep(time.Millisecond * 100)
		}
	}()
	// 发送消息【心跳维持】
	for {
		err = query.Send(&protoc.FileRequest{}) // 心跳维持
		if err != nil {
			panic(err)
		}
		time.Sleep(time.Second) // 每隔100毫秒执行一次心跳维持
	}
}

// 客户端token获取方法
type ClientTokenAuth struct {
}

// 追加APPID和APPKEY信息
func (c ClientTokenAuth) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
	mac := xstring.Mac()
	b, _ := json.Marshal(mac)
	return map[string]string{
		"appid":  "appid",
		"appkey": "appkey",
		"mac":    string(b),
	}, nil
}

// 追加设置，不使用https协议
func (c ClientTokenAuth) RequireTransportSecurity() bool {
	return false
}
